import {
  Args,
  Mutation,
  Query,
  Resolver,
  ResolveProperty,
  Parent,
  Info,
} from '@nestjs/graphql';
import bcrypt from 'bcrypt';

import { UpdateUserDTO } from './dto/update-user.dto';
import { CreatePostDTO } from './dto/create-post.dto';
import { prisma } from '../../generated/prisma-client/blog';
import { QueryDTO } from 'src/common/dto/query.dto';
import { QueryPipe } from 'src/common/pipe/query.pipe';
import { UserInputError } from 'apollo-server';

@Resolver('Post')
export class PostResolver {
  @Query('posts')
  async posts(@Args('query', QueryPipe) { first, skip, orderBy }: QueryDTO) {
    const items = await prisma.posts({
      first,
      skip,
      orderBy,
    });
    const count: number = await prisma
      .postsConnection()
      .aggregate()
      .count();

    return { items, count };
  }

  @Query('queryPosts')
  async queryPosts() {
    const fragment = `
    fragment PostDetail on Post {
      id
      title
      text
      author {
        id
        username
      }
    }`;
    return await prisma.posts().$fragment(fragment);
  }

  // @ResolveProperty('author')
  // async author(@Parent() { id }) {
  //   return await prisma.post({ id }).author();
  // }

  // @ResolveProperty('tags')
  // async tags(@Parent() { id }) {
  //   return await prisma.tags({ where: { posts_some: { id } } });
  // }

  // @ResolveProperty('comments')
  // async comments(@Parent() { id }) {
  //   return await prisma.comments({
  //     where: { AND: [{ post: { id } }, { replyTo: null }] },
  //   });
  // }

  @Query('post')
  async post(@Args('id') id: string) {
    const fragment = `
      fragment PostDetail on Post {
        id
        title
        text
        dateCreated
        dateUpdated
        author {
          id
          username
        }
        tags {
          id
          name
        }
        comments(where: { replyTo: null }) {
          id
          from {
            id
            username
          }
          to {
            id
            username
          }
          text
          dateCreated
          replies {
            id
            from {
              id
              username
            }
            to {
              id
              username
            }
            text
            dateCreated
          }
        }
      }
    `;
    const tags = await prisma.tags({ where: { posts_some: { id } } });
    const comments = await prisma.comments({
      where: { AND: [{ post: { id } }, { replyTo: null }] },
    });

    const author = await prisma.post({ id }).author();
    const post = await prisma.post({ id });
    return { ...post, author, tags, comments };
  }

  @Mutation('createPost')
  async createPost(
    @Args('post')
    { userId, tags, ...data }: CreatePostDTO,
  ) {
    const tagList = await prisma.tags({
      where: { name_in: [...tags] },
    });

    const newTags = tags.filter(tag =>
      tagList.every(({ name }) => name !== tag),
    );

    return await prisma.createPost({
      ...data,
      author: {
        connect: { id: userId },
      },
      tags: {
        create: newTags.map(name => ({ name })),
        connect: tagList.map(({ id }) => ({ id })),
      },
    });
  }

  // @Mutation('updateSysUser')
  // @Authorities('AUTH_SYS_USER_UPDATE')
  // async updateSysUser(
  //   @Args('user')
  //   { id, roleIds, ...data }: UpdateUserDTO,
  // ) {
  //   return await prisma.updateSysUser({
  //     where: { id },
  //     data: {
  //       ...data,
  //       roles: {
  //         set: roleIds.map(item => ({
  //           id: item,
  //         })),
  //       },
  //     },
  //   });
  // }

  // @Mutation('deleteSysUsers')
  // @Authorities('AUTH_SYS_USER_DELETE')
  // async deleteSysUsers(
  //   @Args('ids')
  //   ids: string[],
  // ) {
  //   return await prisma.deleteManySysUsers({ id_in: [...ids] });
  // }
}
